package com.hdax.dm.service.impl;

import cn.hutool.core.lang.Snowflake;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hdax.dm.constant.ErrConstant;
import com.hdax.dm.entity.item.DmItem;
import com.hdax.dm.entity.order.DmOrder;
import com.hdax.dm.entity.order.DmOrderLinkUser;
import com.hdax.dm.entity.scheduler.DmSchedulerSeat;
import com.hdax.dm.entity.scheduler.DmSchedulerSeatPrice;
import com.hdax.dm.entity.user.DmLinkUser;
import com.hdax.dm.exception.DmException;
import com.hdax.dm.feign.ItemFeign;
import com.hdax.dm.feign.LikeUserFeign;
import com.hdax.dm.feign.SeatFeign;
import com.hdax.dm.feign.SeatPriceFeign;
import com.hdax.dm.mappers.OrderMapper;
import com.hdax.dm.service.OrderLinkUserService;
import com.hdax.dm.service.OrderService;
import com.hdax.dm.service.SubmitOrderService;
import com.hdax.dm.utils.response.CommonResponse;
import com.hdax.dm.utils.response.ResponseUtil;
import com.hdax.dm.vo.SubmitOrderVo;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class SubmitOrderSImpl extends ServiceImpl<OrderMapper, DmOrder> implements SubmitOrderService {

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderLinkUserService orderLinkUserService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ItemFeign itemFeign;

    @Autowired
    private SeatFeign seatFeign;

    @Autowired
    private SeatPriceFeign seatPriceFeign;

    @Autowired
    private LikeUserFeign likeUserFeign;

    @Override
    public CommonResponse<Map<String, String>> submitorder(SubmitOrderVo orderVo){
        Map<String,String> orderNo=new HashMap<>();
        //锁定剧场 redis setnx
        Boolean isLock=redisTemplate.opsForValue().setIfAbsent("lock","yes",15, TimeUnit.SECONDS);
        while (!isLock){
            isLock=redisTemplate.opsForValue().setIfAbsent("lock","yes",15, TimeUnit.SECONDS);
        }
        DmOrder order=new DmOrder();
        //订单总金额
        Double totalPrice=0d;

        //1.生成订单编号 IdWorker(雪花算法)   全局唯一
        Snowflake snowflake=new Snowflake(1,1);
        String id=snowflake.nextIdStr();
        //2.查询itemId对应的商品信息
        DmItem item= itemFeign.item(orderVo.getItemId());
        String[] seats = orderVo.getSeatPositions().split(",");

        Double[] prices=new Double[seats.length];
        List<DmSchedulerSeat> seatsUpdate=new ArrayList<>();

        //3.解析座位
        //查询座位相关的属性
        for (int i = 0; i < seats.length; i++) {
            Long x=Long.parseLong(seats[i].split("_")[0]);
            Long y=Long.parseLong(seats[i].split("_")[1]);
            //x y scheduleId查询数据库，保证该座位可以被购买
            DmSchedulerSeat seatList =seatFeign.seat(orderVo.getSchedulerId(),x,y);
            //座位已售出
            if(seatList==null){
                throw new DmException(ErrConstant.ErrCodeConstant.SEAT_ISNULL_CODE,ErrConstant.ErrMsgConstant.SEAT_ISNULL_MSG);
            }

            //查询座位钱
            DmSchedulerSeatPrice seatPrice= seatPriceFeign.price(orderVo.getSchedulerId(),seatList.getAreaLevel());
            //计算订单总金额
            totalPrice+=seatPrice.getPrice();
            prices[i]=seatPrice.getPrice();


            //修改座位的状态，需要锁定座位到某一个订单
            DmSchedulerSeat seat=new DmSchedulerSeat();
            seat.setStatus(3L);
            seat.setOrderNo(id);
            seat.setScheduleId(orderVo.getSchedulerId());
            seat.setX(x);
            seat.setY(y);
            seat.setUserId(orderVo.getUserId());
            seatsUpdate.add(seat);
        }
        /*----------------------------------给order添加数据 start-----------------------------------*/
        order.setOrderNo(id);
        order.setItemId(item.getId());
        order.setItemName(item.getItemName());
        order.setUserId(orderVo.getUserId());
        order.setSchedulerId(orderVo.getSchedulerId());
        order.setOrderType(0L); //未支付
        order.setTotalCount((long) seats.length);  //总票数

        /*----------------------------------给order添加数据 end-----------------------------------*/

        DmOrderLinkUser orderLinkUser= new DmOrderLinkUser();

        //4.解析订单联系人
        String[] linkIds = orderVo.getLinkIds().split(",");
        if (linkIds!=null && linkIds[0].trim().equals("")){
            throw new DmException(ErrConstant.ErrCodeConstant.LINKUSER_ISNULL_CODE,ErrConstant.ErrMsgConstant.LINKUSER_ISNULL_MSG);
        }
        for (int i = 0; i < linkIds.length; i++) {
            Long linkId= Long.valueOf(linkIds[i]);
            //查询当前下单人是否拥有上面linkIds相关联系人信息
            DmLinkUser linkUser= likeUserFeign.likeUser(linkId,orderVo.getUserId());
            //订单联系人添加
            orderLinkUser.setLinkUserId(linkUser.getId());
            orderLinkUser.setLinkUserName(linkUser.getName());
            orderLinkUser.setOrderId(Long.valueOf(id));
            orderLinkUser.setPrice(prices[i]);
            orderLinkUser.setX(Long.parseLong(seats[i].split("_")[0]));
            orderLinkUser.setY(Long.parseLong(seats[i].split("_")[1]));

            //订单联系人新增
        }

        //判断座位购票人是否相等
        if(linkIds.length!=seats.length){
            throw new DmException(ErrConstant.ErrCodeConstant.LINKUSER_SEAT_UNLIKENESS_CODE,ErrConstant.ErrMsgConstant.LINKUSER_SEAT_UNLIKENESS_MSG);
        }


        //5.是否需要保险 +20
        if (orderVo.getIsNeedInsurance()==1){
            totalPrice+=20;
            order.setInsuranceAmount(20D);
        }

        order.setTotalAmount(totalPrice); //总金额
        //是否需要发票
        if (orderVo.getIsNeedInvoice()==1){
            order.setIsNeedInsurance(1L);
            //是否是公司发票
            if (orderVo.getInvoiceType()==0){
                orderVo.setInvoiceType(1L);  //公司
                order.setInvoiceHead("");
                order.setInvoiceNo("");
            }else {
                orderVo.setInvoiceType(0L);  //个人
            }
            //新增订单联系人
            try {
                orderLinkUserService.oderLinkUserAdd(orderLinkUser);
            }catch (Exception e){
                rabbitTemplate.convertAndSend("ex_order_rollback","orderLinkUser",id);
            }

        }


        //三个数据修改（分布式事物）
        //1.新增订单
        try {
            orderService.OrderAdd(order);
        }catch (Exception e){
            rabbitTemplate.convertAndSend("ex_order_rollback","orderLinkUser",id);
            rabbitTemplate.convertAndSend("ex_order_rollback","order",id);
        }
        //3.锁定座位   dm_scheduler_seat (orderNo,userID,status)   批量新增seatsUpdate

        try {
            seatFeign.seatUpdate(seatsUpdate);
//            int num=5/0;
        }catch (Exception e){
            rabbitTemplate.convertAndSend("ex_order_rollback","orderLinkUser",id);
            rabbitTemplate.convertAndSend("ex_order_rollback","order",id);
            rabbitTemplate.convertAndSend("ex_order_rollback","seat",id);
        }
        orderNo.put("orderNo",id);

        //订单倒计时         //PERSISTENT：持久化，永久保存
        rabbitTemplate.convertAndSend("dm_order_exchange","dm.order",order.getOrderNo(),
                message -> {
                    message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                    message.getMessageProperties().setExpiration("60000"); //  1分钟
                    return message;
                });
        //用户下单完成后，需要解锁剧场
        redisTemplate.delete("lock");

        return ResponseUtil.returnSuccess(orderNo);
    }
}
